package com.wootide.cms.common.manager;

import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;


/**
 * 通用的工具类
 * 
 * @author zhangjun
 * @version [1.0, 2010-1-25]
 * @see [相关类/方法]
 * @since [V100R001]
 */
public final class GeneralUtils
{
    
    private GeneralUtils()
    {
        
    }
    
    /**
     * 判断对象是否为null , 为null返回true,否则返回false
     * 
     * @param obj
     *            被判断的对象
     * @return boolean
     */
    public static boolean isNull(Object obj)
    {
        return (null == obj) ? true : false;
    }
    
    /**
     * 判断对象是否为null , 为null返回false,否则返回true
     * 
     * @param obj
     *            被判断的对象
     * @return boolean
     */
    public static boolean isNotNull(Object obj)
    {
        return !isNull(obj);
    }
    
    /**
     * 判断字符串是否为null或者0长度，字符串在判断长度时，先去除前后的空格,空或者0长度返回false,否则返回true
     * 
     * @param str
     *            被判断的字符串
     * 
     * @return boolean
     */
    public static boolean isNotNullOrZeroLenght(String str)
    {
        return !isNullOrZeroLenght(str);
    }
    
    /**
     * 判断str数组是否为null或者0长度，只要有一个空或者0长度返回false, 否则返回true
     * 
     * @param str
     *            String 字符数组
     * @return boolean
     * @author huanghui
     * @see [类、类#方法、类#成员]
     */
    public static boolean isNotNullOrZeroLenght(String... str)
    {
        for (String s : str)
        {
            if (isNullOrZeroLenght(s))
            {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 判断str数组是否为null或者0长度，只要有一个空或者0长度返回true, 否则返回false
     * 
     * @param str
     *            String 字符数组
     * @return boolean
     * @author huanghui
     * @see [类、类#方法、类#成员]
     */
    public static boolean isNullOrZeroLenght(String... str)
    {
        return !isNotNullOrZeroLenght(str);
    }
    
    /**
     * 判断集合对象是否为null或者0大小 , 为空或0大小返回true ,否则返回false
     * 
     * @param c
     *            collection 集合接口
     * @return boolean 布尔值
     * 
     * @author huanghui
     * @see [类、类#方法、类#成员]
     */
    public static boolean isNullOrZeroSize(Collection<? extends Object> c)
    {
        return isNull(c) || c.isEmpty();
    }
    
    /**
     * 判断集合对象是否为null或者0大小 , 为空或0大小返回false, 否则返回true
     * 
     * @param c
     *            collection 集合接口
     * @return boolean 布尔值
     * 
     * @author huanghui
     * @see [类、类#方法、类#成员]
     */
    public static boolean isNotNullOrZeroSize(Collection<? extends Object> c)
    {
        return !isNullOrZeroSize(c);
    }
    
    /**
     * 判断数字类型是否为null或者0，如果是返回true，否则返回false
     * 
     * @param number
     *            被判断的数字
     * @return boolean
     */
    public static boolean isNullOrZero(Number number)
    {
        if (GeneralUtils.isNotNull(number))
        {
            return (number.intValue() != 0) ? false : true;
        }
        return true;
    }
    
    /**
     * 判断数字类型是否不为null或者0，如果是返回true，否则返回false
     * 
     * @param number
     *            被判断的数字
     * @return boolean
     */
    public static boolean isNotNullOrZero(Number number)
    {
        return !isNullOrZero(number);
    }
    
    /**
     * 关闭SOCKET连接
     * 
     * @param socket
     *            Socket
     */
    public static void closeQuietly(Socket socket)
    {
        if (isNotNull(socket))
        {
            try
            {
                socket.close();
            }
            catch (IOException e)
            {
                e.getMessage();
            }
        }
    }
    
    /**
     * 将java.util.Date类型转化位String类型
     * (如果传入时间为系统当前时间，则应该调用getCurrentTimeStamp()方法。)
     * 
     * @param date
     *            要转换的时间
     * @param format
     *            时间格式
     * @return 如果转换成功，返回指定格式字符串，如果转换失败，返回null
     */
    public static String date2String(Date date, String format)
    {
        if (GeneralUtils.isNull(date) || GeneralUtils.isNull(format))
        {
            return null;
        }
        
        return DateFormatUtils.format(date, format);
    }
    
    /**
     * 将字符串时间转换成java.util.Date类型
     * 
     * @param str
     *            要转换的字符串
     * 
     * @param format
     *            时间格式
     * @return 如果转换失败，返回null
     */
    public static Date string2Date(String str, String format)
    {
        if (GeneralUtils.isNull(str) || GeneralUtils.isNull(format))
        {
            return null;
        }
        
        // 定义日期/时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date;
        
        try
        {
            // 转换日期/时间格式
            date = sdf.parse(str);
            // 判断转换前后时间是否一致
            
            if (!str.equals(sdf.format(date)))
            {
                date = null;
            }
        }
        catch (ParseException e)
        {
            date = null;
        }
        
        return date;
    }
    
    /**
     * 获取目录在系统中的绝对路径
     * 
     * 
     * @param path
     *            路径
     * @return Sting
     */
    public static String getAbsolutePath(String path)
    {
        // 如果路进为null，则认为时当前目录
        
        path = (GeneralUtils.isNull(path)) ? "" : path;
        File file = new File(path);
        
        // 获取完整路径
        return FilenameUtils.separatorsToUnix(file.getAbsolutePath());
    }
    
    /**
     * 返回当前时间戳后多少天的日期
     * 
     * @param expressDigit
     *            最后需要表示成的位数
     * 
     * @param addDates
     *            需要在当前时间基础上加的天数
     * 
     * @return String 返回当前时间戳后多少天的日期
     * @see [类、类#方法、类#成员]
     */
    public static String getAddDatesResult(String expressDigit, int addDates)
    {
        Date nowDate = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(nowDate);
        cal.add(Calendar.DAY_OF_MONTH, addDates);
        
        return GeneralUtils.date2String(cal.getTime(), expressDigit);
    }
    
    /**
     * 返回当前时间
     * 
     * @return Date 时间
     * @author huanghui
     * @see [类、类#方法、类#成员]
     */
    public static Date getCurrentDate()
    {
        return Calendar.getInstance().getTime();
    }
    
    /**
     * 根据格式化字符获取时间
     * 
     * 
     * @param dateStr
     *            字符串时间
     * 
     * @param pattern
     *            格式化方式
     * 
     * @return Date Date
     * @see [类、类#方法、类#成员]
     */
    public static Date getDate(String dateStr, String pattern)
    {
        Date date = null;
        try
        {
            date = new SimpleDateFormat(pattern).parse(dateStr);
        }
        catch (ParseException e)
        {
            return null;
        }
        return date;
    }
    
    /**
     * 将指定的Byte[]类型转换成byte[]类型
     * 
     * @param src
     *            Byte[]数组
     * @return byte[]
     * @see [类、类#方法、类#成员]
     */
    public static byte[] transformArray(Byte[] src)
    {
        return ArrayUtils.toPrimitive(src);
    }
    
    /**
     * 将指定的byte[]类型转换成Byte[]类型
     * 
     * @param src
     *            byte[]数组
     * @return Byte[]
     * @see [类、类#方法、类#成员]
     */
    public static Byte[] transformArray(byte[] src)
    {
        return ArrayUtils.toObject(src);
    }
    
    /**
     * 根据指定模式，对字符串进行转换并返回转化结果。
     * 
     * 
     * 
     * @param strToBeReplaced -
     *            待替换的字符串
     * 
     * 
     * @param regexs -
     *            正则表达式字符串及其替换值
     * 
     * 
     * @return - 替换后的字符串
     * 
     * 
     */
    public static String getFormattedString(String strToBeReplaced,
            Map<String, String> regexs)
    {
        // 原始字符串为NULL或者为空，直接返回空字符串
        if (StringUtils.isBlank(strToBeReplaced))
        {
            return "";
        }
        
        // 没有指定正则表达式字符串，直接返回原始字符串
        if (isNull(regexs) || regexs.isEmpty())
        {
            return strToBeReplaced;
        }
        
        // 匹配模式
        Pattern pattern;
        
        // 匹配器
        
        Matcher matcher;
        
        // 遍历正则表达式字符串，替换原始字符串数据
        for (Entry<String, String> entryregex : regexs.entrySet())
        {
            // 编译匹配模式
            pattern = Pattern.compile("\\$\\{" + entryregex.getKey() + "\\}");
            
            // 匹配原始字符串
            
            matcher = pattern.matcher(strToBeReplaced);
            
            // 执行字符串替换
            
            strToBeReplaced = matcher.replaceAll(StringUtils.trimToEmpty(entryregex.getValue()));
        }
        
        return strToBeReplaced;
    }
    
    /**
     * 将以特定字符作为分隔符的字符串转换为Set集合
     * 
     * @param strToBeConverted -
     *            待转换的字符串
     * 
     * 
     * @param separator -
     *            分隔符
     * 
     * 
     * @return - 转换后的列表对象
     */
    public static List<String> splitStringUseSpecifiedSeparator(
            String strToBeConverted, String separator)
    {
        // 转换后集合对象，初始设置为空。
        
        List<String> resultList = new ArrayList<String>();
        
        // 原始字符串为NULL或者为空，直接返回空Set
        if (StringUtils.isEmpty(strToBeConverted))
        {
            return resultList;
        }
        
        // 分隔符为NUlL或者空，返回只包含原始字符串的Set
        if (StringUtils.isEmpty(separator))
        {
            resultList.add(strToBeConverted);
        }
        
        // 按照指定分隔符拆分字符串
        String[] arrayString = strToBeConverted.split(separator);
        
        // 遍历数组，组装到Set集合中。方便调用程序处理。
        
        for (String str : arrayString)
        {
            resultList.add(str);
        }
        
        return resultList;
    }
    
    /**
     * 将文件路径转为本地显示，并以文件分隔符结束.
     * 
     * @param path {@link String} 待转换的路径
     * @return {@link String} 本地显示的文件路径，以文件分隔符结束
     */
    public static String toLocalFilePathWithSeperatorEnd(String path)
    {
        String tmp = toLocalFilePath(path);
        if (tmp.lastIndexOf(File.separator) < tmp.length() - 1)
        {
            return tmp + File.separator;
        }
        else
        {
            return tmp;
        }
    }
    
    /**
     * 将文件路径转为本地表示.
     * 
     * @param path {@link String} 待转换的路径
     * @return {@link String} 本地表示
     */
    public static String toLocalFilePath(String path)
    {
        return path.replace("/", File.separator).replace("\\", File.separator);
    }
    
    /**
     * 列出指定目录下的文件名（仅文件名，不含路径），名称包含特定字符串
     * （可以使用wildcard）的文件.
     * 
     * @param dir {@link String} 目录
     * @param nameFilter {@link String} 名称过滤器（可以使用wildcard）
     * @param capSense boolean 大小写敏感
     * @param fullPath boolean 是否返回完整路径
     * @return {@link File}[] 文件列表
     * @throws IOException IO异常
     */
    public static String[] listAllFiles(String dir, String nameFilter, boolean capSense, boolean fullPath) throws IOException {
        File dirx = new File(dir);
        if (dirx.exists() && dirx.isDirectory()) {
            String[] filenames = dirx.list(new SimpleFilenameFilter(nameFilter, capSense));
            if (fullPath) {
                for (int i = 0; i < filenames.length; i++) {
                    filenames[i] = toLocalFilePathWithSeperatorEnd(dir) + filenames[i];
                }
            }
            return filenames;
        } else {
            throw new IOException("\"" + dir + "\" doesn't exist or isn't a directory");
        }
    }
    
}
